<?php


namespace apps\marriage\core\service;


use apps\marriage\core\model\SystemNotice;
use apps\marriage\core\model\UserAccountBook;
use apps\marriage\core\model\UserPlatform;
use apps\marriage\core\model\UserSystemNotice;
use apps\marriage\core\model\UserWithdrawCash;
use apps\marriage\core\payment\WxPay;
use think\Exception;
use think\facade\Log;
use vm\com\BaseService;
use vm\org\queue\QueueFactory;

class UserWithdrawCashService extends BaseService
{

    /**
     * @return UserWithdrawCash
     */
    protected function getModel()
    {
        return new UserWithdrawCash();
    }

    /**
     * @return UserService
     */
    private function getUserService()
    {
        return service('User', SERVICE_NAMESPACE);
    }

    /**
     * @return UserAccountBookService
     */
    private function getUserAccountService()
    {
        return service('UserAccountBook', SERVICE_NAMESPACE);
    }

    /**
     * @return SiteConfigService
     */
    private function getSiteConfigService()
    {
        return service('SiteConfig', SERVICE_NAMESPACE);
    }

    /**
     * @return SystemNoticeService
     */
    protected function getSystemNoticeService()
    {
        return service('SystemNotice', SERVICE_NAMESPACE);
    }

    /**
     * @return UserSystemNoticeService
     */
    protected function getUserSystemNoticeService()
    {
        return service('UserSystemNotice', SERVICE_NAMESPACE);
    }

    /**
     * @return UserPlatformService
     */
    protected function getUserPlatformService()
    {
        return service('UserPlatform', SERVICE_NAMESPACE);
    }

    /**
     * @return UserWithdrawAccountService
     */
    protected function getUserWithdrawAccountService()
    {
        return service('UserWithdrawAccount', SERVICE_NAMESPACE);
    }

    public function format($data)
    {
        switch ($data['status']) {
            case UserWithdrawCash::STATUS_AUDITTING:
                $data['status_label'] = '审核中';
                break;
            case UserWithdrawCash::STATUS_WAIT_PAY:
                $data['status_label'] = '待打款';
                break;
            case UserWithdrawCash::STATUS_PAIED:
                $data['status_label'] = '已打款';
                break;
            case UserWithdrawCash::STATUS_REJECTED:
                $data['status_label'] = '未通过审核';
                break;
            default:
                break;
        }

        switch ($data['pay_type']) {
            case UserWithdrawCash::PAY_TYPE_WECHAT:
                $data['pay_type_label'] = '微信支付';
                break;
            case UserWithdrawCash::PAY_TYPE_ALIPAY:
                $data['pay_type_label'] = '支付宝';
                break;
            default:
                break;
        }

        return $data;
    }

    /**
     * 申请提现
     * @param int $userId               --用户ID
     * @param float $amount             --金额
     * @return false
     * @throws Exception
     */
    public function onApply($userId, $amount)
    {
        if(!is_numeric($amount) || $amount <= 0) {
            throw new Exception('参数错误');
        }
        $withdraw_cash_min_amount = $this->getSiteConfigService()->getValueByCode('withdraw_cash_min_amount');
        if ($amount < $withdraw_cash_min_amount) {
            throw new Exception('提现金额不能少于'.$withdraw_cash_min_amount.'元');
        }

        $data2 = [
            'user_id' => $userId,
            'amount' => $amount,
            'status' => UserWithdrawCash::STATUS_AUDITTING,
            'apply_time' => time()
        ];
        $applyId = $this->create($data2);
        $this->getUserService()->applyWithdraw($userId, $amount, $applyId);
        return true;
    }

    /**
     * 拒绝提现申请
     * @param int $id
     * @param string $remark        --备注信息
     * @return bool
     * @throws Exception
     */
    public function onReject($id, $remark)
    {
        $result = $this->update([
            'status' => UserWithdrawCash::STATUS_REJECTED,
            'remark' => $remark
        ], [
            'id' => $id,
            'status' => UserWithdrawCash::STATUS_AUDITTING
        ]);
        $record = $this->getByPk($id);
        $this->getUserService()->rejectWithdraw($record['user_id'], $record['amount'], $id);

        $user = $this->getUserService()->getByPk($record['user_id']);

        // 发送通知
        $systemNoticeId = $this->getSystemNoticeService()->create([
            'title' => '提现申请处理结果',
            'content' => '您的提现申请已被拒绝。',
            'type' => SystemNotice::TYPE_SINGLE,
            'status' => SystemNotice::STATUS_PULLED,
            'recipient_id' => $record['user_id'],
            'manager_id' => 0,
            'url' => json_encode([
                'weapp' => '/pages/my/wallet/withdraw/list',
                'web' => '/my_wallet_withdraw',
                'app' => '/my/wallet/withdraw/list'
            ])
        ]);
        $this->getUserSystemNoticeService()->create([
            'system_notice_id' => $systemNoticeId,
            'recipient_id' => $record['user_id'],
            'status' => UserSystemNotice::STATUS_WAIT_READ,
            'pull_time' => time()
        ]);

        // 给被申请人发送公众号通知
        try {
            if($this->getUserPlatformService()->checkUserSubscribedMpAccount($record['user_id'])) {
                $userPlatform = $this->getUserPlatformService()->info([
                    'user_id' => $record['user_id'],
                    'platform' => UserPlatform::PLATFORM_WX_MP
                ]);
                if($userPlatform) {
                    $openid = $userPlatform['open_id'];
                    $wechatConfig = config('wechat');
                    $msgTemplateId = $wechatConfig['mp_msg_templates']['withdraw_audit_remind'];
                    $msgData = [
                        'first' => [
                            'value' => '提现申请已被拒绝'
                        ],
                        'keyword1' => [
                            'value' => $user['nick']
                        ],
                        'keyword2' => [
                            'value' => date('Y-m-d H:i:s', $record['apply_time'])
                        ],
                        'keyword3' => [
                            'value' => $record['amount']
                        ],
                        'remark' => [
                            'value' => empty($record['remark']) ? 'N/A' : $record['remark']
                        ]
                    ];
                    $url = $this->getSiteConfigService()->getValueByCode('mp_site') . '/my_wallet_withdraw';
                    $miniprogram = null;

                    $queueConfig = config('queue');
                    $queueHandler = QueueFactory::instance();
                    $queueHandler->set($queueConfig['queues']['mp_msg'], [
                        'openid' => $openid,
                        'template_id' => $msgTemplateId,
                        'data' => $msgData,
                        'url' => $url,
                        'miniprogram' => $miniprogram
                    ]);
                }
            }
        } catch (\Exception $e) {
            $log = 'FILE:' . $e->getFile() . "\r\n" . 'LINE:' . $e->getLine(). "\r\n" . 'MSG:' . $e->getMessage();
            Log::error($log);
        }
        return true;
    }

    /**
     * 同意提现申请
     * @param int $id
     * @return bool
     * @throws Exception
     */
    public function onAgree($id)
    {
        $result = $this->update([
            'status' => UserWithdrawCash::STATUS_WAIT_PAY
        ], [
            'id' => $id,
            'status' => UserWithdrawCash::STATUS_AUDITTING
        ]);
        $record = $this->getByPk($id);
        $user = $this->getUserService()->getByPk($record['user_id']);
        // 发送通知
        $systemNoticeId = $this->getSystemNoticeService()->create([
            'title' => '提现申请处理结果',
            'content' => '您的提现申请已审核通过。',
            'type' => SystemNotice::TYPE_SINGLE,
            'status' => SystemNotice::STATUS_PULLED,
            'recipient_id' => $record['user_id'],
            'manager_id' => 0,
            'url' => json_encode([
                'weapp' => '/pages/my/wallet/withdraw/list',
                'web' => '/my_wallet_withdraw',
                'app' => '/my/wallet/withdraw/list'
            ])
        ]);
        $this->getUserSystemNoticeService()->create([
            'system_notice_id' => $systemNoticeId,
            'recipient_id' => $record['user_id'],
            'status' => UserSystemNotice::STATUS_WAIT_READ,
            'pull_time' => time()
        ]);

        // 给被申请人发送公众号通知
        try {
            if($this->getUserPlatformService()->checkUserSubscribedMpAccount($record['user_id'])) {
                $userPlatform = $this->getUserPlatformService()->info([
                    'user_id' => $record['user_id'],
                    'platform' => UserPlatform::PLATFORM_WX_MP
                ]);
                if($userPlatform) {
                    $openid = $userPlatform['open_id'];
                    $wechatConfig = config('wechat');
                    $msgTemplateId = $wechatConfig['mp_msg_templates']['withdraw_audit_remind'];
                    $msgData = [
                        'first' => [
                            'value' => '提现申请审核通过'
                        ],
                        'keyword1' => [
                            'value' => $user['nick']
                        ],
                        'keyword2' => [
                            'value' => date('Y-m-d H:i:s', $record['apply_time'])
                        ],
                        'keyword3' => [
                            'value' => $record['amount']
                        ],
                        'remark' => [
                            'value' => '您的提现已通过审核'
                        ]
                    ];
                    $url = $this->getSiteConfigService()->getValueByCode('mp_site') . '/my_wallet_withdraw';
                    $miniprogram = null;

                    $queueConfig = config('queue');
                    $queueHandler = QueueFactory::instance();
                    $queueHandler->set($queueConfig['queues']['mp_msg'], [
                        'openid' => $openid,
                        'template_id' => $msgTemplateId,
                        'data' => $msgData,
                        'url' => $url,
                        'miniprogram' => $miniprogram
                    ]);
                }
            }
        } catch (\Exception $e) {
            $log = 'FILE:' . $e->getFile() . "\r\n" . 'LINE:' . $e->getLine(). "\r\n" . 'MSG:' . $e->getMessage();
            Log::error($log);
        }
    }

    /**
     * 给申请人打款
     * @param int $id
     */
    public function onPay($id)
    {
        $record = $this->getByPk($id);
        $withdrawAccount = $this->getUserWithdrawAccountService()->getUserId($record['user_id']);

        if(empty($record['trade_no'])) {
            $tradeNo = date('YmdHis') . rand_string(6, 1);
            while (parent::info(['trade_no' => $tradeNo])) {
                $tradeNo = date('YmdHis') . rand_string(6, 1);
            }
        } else {
            $tradeNo = $record['trade_no'];
        }

        $siteConfigService = $this->getSiteConfigService();
        $appName = $siteConfigService->getValueByCode('app_name');
        $appId = $siteConfigService->getValueByCode('weixin_mp_app_id');
        $payConfig = [
            'app_id' => $appId,
            'app_secret' => $siteConfigService->getValueByCode('weixin_mp_app_secret'),
            'mch_id' => $siteConfigService->getValueByCode('weixin_mp_mch_id'),
            'pay_key' => $siteConfigService->getValueByCode('weixin_mp_pay_sign_key'),
        ];
        $payment = new WxPay($payConfig);

        $userPlaform = $this->getUserPlatformService()->getByUserIdWithAppid($appId, $record['user_id']);
        if(empty($userPlaform)) {
            throw new Exception('该用户未在公众号登录过，无法用微信转账');
        }

        $result = $payment->transfer($tradeNo,$userPlaform['open_id'], $record['amount'], $appName . '-提现', $withdrawAccount['alipay_name']);
        $res = $this->update([
            'trade_no' => $tradeNo,
            'pay_type' => UserWithdrawCash::PAY_TYPE_WECHAT,
            'payment_transaction_id' => $result['payment_no'],
            'pay_time' => strtotime($result['payment_time']),
            'alipay_name' => $withdrawAccount['alipay_name'],
            'alipay_account' => $withdrawAccount['alipay_account'],
        ], [
            'id' => $id,
            'status' => UserWithdrawCash::STATUS_WAIT_PAY
        ]);
        if(!$res) {
            throw new Exception('转账失败');
        }
        $this->onFinish($id);
    }

    /**
     * 完成打款
     * @param int $id
     * @throws Exception
     */
    public function onFinish($id)
    {
        $result = $this->update([
            'status' => UserWithdrawCash::STATUS_PAIED
        ], [
            'id' => $id,
            'status' => UserWithdrawCash::STATUS_WAIT_PAY
        ]);
        if(!$result) {
            throw new Exception('操作失败');
        }
        $record = $this->getByPk($id);
        $record = $this->format($record);
        $this->getUserService()->finishWithdraw($record['user_id'], $record['amount']);
        // 发送通知
        $systemNoticeId = $this->getSystemNoticeService()->create([
            'title' => '提现已打款',
            'content' => '您的提现已打款，请注意查收。',
            'type' => SystemNotice::TYPE_SINGLE,
            'status' => SystemNotice::STATUS_PULLED,
            'recipient_id' => $record['user_id'],
            'manager_id' => 0,
            'url' => json_encode([
                'weapp' => '/pages/my/wallet/withdraw/list',
                'web' => '/my_wallet_withdraw',
                'app' => '/my/wallet/withdraw/list'
            ])
        ]);
        $this->getUserSystemNoticeService()->create([
            'system_notice_id' => $systemNoticeId,
            'recipient_id' => $record['user_id'],
            'status' => UserSystemNotice::STATUS_WAIT_READ,
            'pull_time' => time()
        ]);

        // 给被申请人发送公众号通知
        try {
            if($this->getUserPlatformService()->checkUserSubscribedMpAccount($record['user_id'])) {
                $userPlatform = $this->getUserPlatformService()->info([
                    'user_id' => $record['user_id'],
                    'platform' => UserPlatform::PLATFORM_WX_MP
                ]);
                if($userPlatform) {
                    $openid = $userPlatform['open_id'];
                    $wechatConfig = config('wechat');
                    $msgTemplateId = $wechatConfig['mp_msg_templates']['withdraw_payed_notice'];
                    $msgData = [
                        'first' => [
                            'value' => '提现已打款'
                        ],
                        'keyword1' => [
                            'value' => date('Y-m-d H:i:s', $record['apply_time'])
                        ],
                        'keyword2' => [
                            'value' => $record['pay_type_label']
                        ],
                        'keyword3' => [
                            'value' => $record['amount']
                        ],
                        'keyword4' => [
                            'value' => 0.00
                        ],
                        'keyword5' => [
                            'value' => $record['amount']
                        ],
                        'remark' => [
                            'value' => '提现已打款，请查收'
                        ]
                    ];
                    $url = $this->getSiteConfigService()->getValueByCode('mp_site') . '/my_wallet_withdraw';
                    $miniprogram = null;

                    $queueConfig = config('queue');
                    $queueHandler = QueueFactory::instance();
                    $queueHandler->set($queueConfig['queues']['mp_msg'], [
                        'openid' => $openid,
                        'template_id' => $msgTemplateId,
                        'data' => $msgData,
                        'url' => $url,
                        'miniprogram' => $miniprogram
                    ]);
                }
            }
        } catch (\Exception $e) {
            $log = 'FILE:' . $e->getFile() . "\r\n" . 'LINE:' . $e->getLine(). "\r\n" . 'MSG:' . $e->getMessage();
            Log::error($log);
        }
    }
}